<!DOCTYPE html>
<html lang="en" class="js csstransforms3d">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <meta name="generator" content="Hugo 0.20.7" />
    <meta name="description" content="">


    <link rel="shortcut icon" href="http://shardingjdbc.io/document/legacy/2.x/cn/img/favicon.png" type="image/x-icon" />

    
    <title>分页及子查询</title>
    <link href="http://ovfotjrsi.bkt.clouddn.com/docs/css/nucleus.css" rel="stylesheet">
    <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
    <link href="http://ovfotjrsi.bkt.clouddn.com/docs/css/theme.css" rel="stylesheet">
    <link href="http://ovfotjrsi.bkt.clouddn.com/docs/css/hugo-theme.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
    <style type="text/css">:root #header + #content > #left > #rlblock_left
    {display:none !important;}</style>
    <link rel="stylesheet" href="http://cdn.bootcss.com/highlight.js/9.8.0/styles/monokai-sublime.min.css">
<link rel="stylesheet" href="http://ovfotjrsi.bkt.clouddn.com/docs/css/style.css">
  </head>
  <body class="" data-url="/02-guide/subquery/">
    
    <nav id="sidebar">
  <div id="header-wrapper">
    <div id="header">
      <img src="http://ovfotjrsi.bkt.clouddn.com/docs/img/sharding-jdbc.png" />
    </div>
</div>
  <div class="highlightable">
    <ul class="topics">
      
        
        
          
          
            
          
        
          
          
            
          
        
          
          
            
          
        
          
          
            
          
        
        
        
          
        
          
        
          
        
          
        
      
      
      
      

      
      
      
        
          
          
            
          
        
      
      
      

      <li class="dd-item  " data-nav-id="/00-overview/">
        <a href="http://shardingjdbc.io/document/legacy/2.x/cn/00-overview/">
          <span>
            
              <b>0. </b>
            
             概览
            
           </span>
        </a>
        
        <ul>
          
            <li class="dd-item " data-nav-id="/00-overview/intro/">
              <a href="http://shardingjdbc.io/document/legacy/2.x/cn/00-overview/intro/">
                <span>简介     </i></span>
              </a>
            </li>
          
            <li class="dd-item " data-nav-id="/00-overview/news/">
              <a href="http://shardingjdbc.io/document/legacy/2.x/cn/00-overview/news/">
                <span>新闻     </i></span>
              </a>
            </li>
          
            <li class="dd-item " data-nav-id="/00-overview/contribution/">
              <a href="http://shardingjdbc.io/document/legacy/2.x/cn/00-overview/contribution/">
                <span>贡献代码     </i></span>
              </a>
            </li>
          
        </ul>
        
      </li>
      
      
      

      
      
      
        
          
          
            
          
        
      
      
      

      <li class="dd-item  " data-nav-id="/01-start/">
        <a href="http://shardingjdbc.io/document/legacy/2.x/cn/01-start/">
          <span>
            
              <b>1. </b>
            
             起航
            
           </span>
        </a>
        
        <ul>
          
            <li class="dd-item " data-nav-id="/01-start/quick-start/">
              <a href="http://shardingjdbc.io/document/legacy/2.x/cn/01-start/quick-start/">
                <span>快速入门     </i></span>
              </a>
            </li>
          
            <li class="dd-item " data-nav-id="/01-start/code-demo/">
              <a href="http://shardingjdbc.io/document/legacy/2.x/cn/01-start/code-demo/">
                <span>使用示例     </i></span>
              </a>
            </li>
          
            <li class="dd-item " data-nav-id="/01-start/faq/">
              <a href="http://shardingjdbc.io/document/legacy/2.x/cn/01-start/faq/">
                <span>FAQ     </i></span>
              </a>
            </li>
          
            <li class="dd-item " data-nav-id="/01-start/features/">
              <a href="http://shardingjdbc.io/document/legacy/2.x/cn/01-start/features/">
                <span>详细功能列表     </i></span>
              </a>
            </li>
          
            <li class="dd-item " data-nav-id="/01-start/limitations/">
              <a href="http://shardingjdbc.io/document/legacy/2.x/cn/01-start/limitations/">
                <span>使用限制     </i></span>
              </a>
            </li>
          
            <li class="dd-item " data-nav-id="/01-start/sql-supported/">
              <a href="http://shardingjdbc.io/document/legacy/2.x/cn/01-start/sql-supported/">
                <span>SQL支持详细列表     </i></span>
              </a>
            </li>
          
            <li class="dd-item " data-nav-id="/01-start/stress-test/">
              <a href="http://shardingjdbc.io/document/legacy/2.x/cn/01-start/stress-test/">
                <span>性能测试报告     </i></span>
              </a>
            </li>
          
        </ul>
        
      </li>
      
      
      

      
      
      
        
          
          
            
          
        
      
      
      

      <li class="dd-item  parent" data-nav-id="/02-guide/">
        <a href="http://shardingjdbc.io/document/legacy/2.x/cn/02-guide/">
          <span>
            
              <b>2. </b>
            
             使用指南
            
           </span>
        </a>
        
        <ul>
          
            <li class="dd-item " data-nav-id="/02-guide/concepts/">
              <a href="http://shardingjdbc.io/document/legacy/2.x/cn/02-guide/concepts/">
                <span>核心概念     </i></span>
              </a>
            </li>
          
            <li class="dd-item " data-nav-id="/02-guide/sharding/">
              <a href="http://shardingjdbc.io/document/legacy/2.x/cn/02-guide/sharding/">
                <span>分库分表     </i></span>
              </a>
            </li>
          
            <li class="dd-item " data-nav-id="/02-guide/master-slave/">
              <a href="http://shardingjdbc.io/document/legacy/2.x/cn/02-guide/master-slave/">
                <span>读写分离     </i></span>
              </a>
            </li>
          
            <li class="dd-item " data-nav-id="/02-guide/config_domain/">
              <a href="http://shardingjdbc.io/document/legacy/2.x/cn/02-guide/config_domain/">
                <span>配置域模型     </i></span>
              </a>
            </li>
          
            <li class="dd-item " data-nav-id="/02-guide/configuration/">
              <a href="http://shardingjdbc.io/document/legacy/2.x/cn/02-guide/configuration/">
                <span>配置手册     </i></span>
              </a>
            </li>
          
            <li class="dd-item " data-nav-id="/02-guide/orchestration/">
              <a href="http://shardingjdbc.io/document/legacy/2.x/cn/02-guide/orchestration/">
                <span>编排治理     </i></span>
              </a>
            </li>
          
            <li class="dd-item " data-nav-id="/02-guide/hint-sharding-value/">
              <a href="http://shardingjdbc.io/document/legacy/2.x/cn/02-guide/hint-sharding-value/">
                <span>强制路由     </i></span>
              </a>
            </li>
          
            <li class="dd-item " data-nav-id="/02-guide/key-generator/">
              <a href="http://shardingjdbc.io/document/legacy/2.x/cn/02-guide/key-generator/">
                <span>分布式主键     </i></span>
              </a>
            </li>
          
            <li class="dd-item " data-nav-id="/02-guide/transaction/">
              <a href="http://shardingjdbc.io/document/legacy/2.x/cn/02-guide/transaction/">
                <span>事务支持     </i></span>
              </a>
            </li>
          
            <li class="dd-item active" data-nav-id="/02-guide/subquery/">
              <a href="http://shardingjdbc.io/document/legacy/2.x/cn/02-guide/subquery/">
                <span>分页及子查询     </i></span>
              </a>
            </li>
          
            <li class="dd-item " data-nav-id="/02-guide/test-framework/">
              <a href="http://shardingjdbc.io/document/legacy/2.x/cn/02-guide/test-framework/">
                <span>测试引擎     </i></span>
              </a>
            </li>
          
            <li class="dd-item " data-nav-id="/02-guide/apm/">
              <a href="http://shardingjdbc.io/document/legacy/2.x/cn/02-guide/apm/">
                <span>应用性能监控     </i></span>
              </a>
            </li>
          
            <li class="dd-item " data-nav-id="/02-guide/sharding-jdbc-server/">
              <a href="http://shardingjdbc.io/document/legacy/2.x/cn/02-guide/sharding-jdbc-server/">
                <span>Sharding-JDBC-Server     </i></span>
              </a>
            </li>
          
        </ul>
        
      </li>
      
      
      

      
      
      
        
          
          
            
          
        
      
      
      

      <li class="dd-item  " data-nav-id="/03-design/">
        <a href="http://shardingjdbc.io/document/legacy/2.x/cn/03-design/">
          <span>
            
              <b>3. </b>
            
             设计规划
            
           </span>
        </a>
        
        <ul>
          
            <li class="dd-item " data-nav-id="/03-design/architecture/">
              <a href="http://shardingjdbc.io/document/legacy/2.x/cn/03-design/architecture/">
                <span>架构设计     </i></span>
              </a>
            </li>
          
            <li class="dd-item " data-nav-id="/03-design/module/">
              <a href="http://shardingjdbc.io/document/legacy/2.x/cn/03-design/module/">
                <span>模块说明     </i></span>
              </a>
            </li>
          
            <li class="dd-item " data-nav-id="/03-design/roadmap/">
              <a href="http://shardingjdbc.io/document/legacy/2.x/cn/03-design/roadmap/">
                <span>未来线路规划     </i></span>
              </a>
            </li>
          
        </ul>
        
      </li>
      
      
    </ul>
    <hr>
     
  </div>
</nav>

        <section id="body">
        <div id="overlay"></div>

        <div class="padding highlightable">

            <div id="top-bar">
              
              <div id="breadcrumbs" itemscope="" itemtype="http://data-vocabulary.org/Breadcrumb">
                  <span id="sidebar-toggle-span">
                      <a href="#" id="sidebar-toggle" data-sidebar-toggle="">
                        <i class="fa fa-bars"></i>
                      </a>
                  </span>
                
                <span id="toc-menu"><a href=""><i class="fa fa-list-alt"></i></a></span>
                
                
                  
                  
                  
                    
                    
                <a href="http://shardingjdbc.io/document/legacy/2.x/cn/02-guide/" itemprop="url"><span itemprop="title">使用指南</span></a> <i class="fa fa-angle-right"></i>
                    
                  
                
                <span itemprop="title"> 分页及子查询</span>
              </div>
              
                  <div class="progress">
    <div class="wrapper">
<nav id="TableOfContents">
<ul>
<li><a href="#分页性能">分页性能</a>
<ul>
<li><a href="#性能瓶颈">性能瓶颈</a></li>
<li><a href="#sharding-jdbc的优化">Sharding-JDBC的优化</a></li>
<li><a href="#更好的分页解决方案">更好的分页解决方案</a></li>
</ul></li>
<li><a href="#分页子查询">分页子查询</a>
<ul>
<li><a href="#oracle">Oracle</a></li>
<li><a href="#sqlserver">SQLServer</a></li>
<li><a href="#mysql-postgresql">MySQL, PostgreSQL</a></li>
</ul></li>
<li><a href="#其他子查询">其他子查询</a></li>
</ul>
</nav>
    </div>
</div>

              

            </div>
            
              <div id="body-inner">
                
                <h1>分页及子查询</h1>
                



<p>Sharding-JDBC完全支持MySQL、PostgreSQL和Oracle的分页查询，SQLServer由于分页查询较为复杂，仅部分支持。</p>

<h1 id="分页性能">分页性能</h1>

<h2 id="性能瓶颈">性能瓶颈</h2>

<p>查询偏移量过大的分页会导致数据库获取数据性能低下，以MySQL为例：</p>

<pre><code class="language-sql">SELECT * FROM t_order ORDER BY id LIMIT 1000000, 10
</code></pre>

<p>这句SQL会使得MySQL在无法利用索引的情况下跳过1000000条记录后，再获取10条记录，其性能可想而知。而在分库分表的情况下（假设分为2个库），为了保证数据的正确性，SQL会改写为：</p>

<pre><code class="language-sql">SELECT * FROM t_order ORDER BY id LIMIT 0, 1000010
</code></pre>

<p>即将偏移量前的记录全部取出，并仅获取排序后的最后10条记录。这会在数据库本身就执行很慢的情况下，进一步加剧性能瓶颈。因为原SQL仅需要传输10条记录至客户端，而改写之后的SQL则会传输1000010*2的记录至客户端。</p>

<h2 id="sharding-jdbc的优化">Sharding-JDBC的优化</h2>

<p>Sharding-JDBC进行了2个方面的优化。</p>

<p>首先，Sharding-JDBC采用流式处理 + 归并排序的方式来避免内存的过量占用。Sharding-JDBC的SQL改写，不可避免的占用了额外的带宽，但并不会导致内存暴涨。
与直觉不同，大多数人认为Sharding-JDBC会将1000010*2记录全部加载至内存，进而占用大量内存而导致内存溢出。
但由于每个结果集的记录是有序的，因此Sharding-JDBC每次比较仅获取各个分片的当前结果集记录，驻留在内存中的记录仅为当前路由到的分片的结果集的当前游标指向而已。
对于本身即有序的待排序对象，归并排序的时间复杂度仅为O(n)，性能损耗很小。</p>

<p>其次，Sharding-JDBC对仅落至单分片的查询进行进一步优化。落至单分片查询的请求并不需要改写SQL也可以保证记录的正确性，因此在此种情况下，Sharding-JDBC并未进行SQL改写，从而达到节省带宽的目的。</p>

<h2 id="更好的分页解决方案">更好的分页解决方案</h2>

<p>由于LIMIT并不能通过索引查询数据，因此如果可以保证ID的连续性，通过ID进行分页是比较好的解决方案：</p>

<pre><code class="language-sql">SELECT * FROM t_order WHERE id &gt; 100000 AND id &lt;= 100010 ORDER BY id
</code></pre>

<p>或通过记录上次查询结果的最后一条记录的ID进行下一页的查询：</p>

<pre><code class="language-sql">SELECT * FROM t_order WHERE id &gt; 100000 LIMIT 10
</code></pre>

<h1 id="分页子查询">分页子查询</h1>

<p>Oracle和SQLServer的分页都需要通过子查询来处理，Sharding-JDBC支持分页相关的子查询。</p>

<h2 id="oracle">Oracle</h2>

<p>Sharding-JDBC支持使用rownum进行分页：</p>

<pre><code class="language-sql">SELECT * FROM (SELECT row_.*, rownum rownum_ FROM (SELECT o.order_id as order_id FROM t_order o JOIN t_order_item i ON o.order_id = i.order_id) row_ WHERE rownum &lt;= ?) WHERE rownum &gt; ?
</code></pre>

<p>目前不支持rownum + BETWEEN的分页方式。</p>

<h2 id="sqlserver">SQLServer</h2>

<p>Sharding-JDBC支持使用TOP + ROW_NUMBER() OVER配合进行分页：</p>

<pre><code class="language-sql">SELECT * FROM (SELECT TOP (?) ROW_NUMBER() OVER (ORDER BY o.order_id DESC) AS rownum, * FROM t_order o) AS temp WHERE temp.rownum &gt; ? ORDER BY temp.order_id
</code></pre>

<p>Sharding-JDBC也支持SQLServer 2012之后的OFFSET FETCH的分页方式：</p>

<pre><code class="language-sql">SELECT * FROM t_order o ORDER BY id OFFSET ? ROW FETCH NEXT ? ROWS ONLY
</code></pre>

<p>目前不支持使用WITH xxx AS (SELECT &hellip;)的方式进行分页。由于Hibernate自动生成的SQLServer分页语句使用了WITH语句，因此目前并不支持基于Hibernate的SQLServer分页。
目前也不支持使用两个TOP + 子查询的方式实现分页。</p>

<h2 id="mysql-postgresql">MySQL, PostgreSQL</h2>

<p>MySQL和PostgreSQL都支持LIMIT分页，无需子查询：</p>

<pre><code class="language-sql">SELECT * FROM t_order o ORDER BY id LIMIT ? OFFSET ?
</code></pre>

<h1 id="其他子查询">其他子查询</h1>

<p>Sharding-JDBC除了分页子查询的支持之外，也支持同等模式的子查询。无论嵌套多少层，Sharding-JDBC都可以解析至第一个包含数据表的子查询，一旦在下层嵌套中再次找到包含数据表的子查询将直接抛出解析异常。</p>

<p>例如，以下子查询可以支持：</p>

<pre><code class="language-sql">SELECT COUNT(*) FROM (SELECT * FROM t_order o)
</code></pre>

<p>以下子查询不支持：</p>

<pre><code class="language-sql">SELECT COUNT(*) FROM (SELECT * FROM t_order o WHERE o.id IN (SELECT id FROM t_order WHERE status = ?))
</code></pre>

<p>简单来说，通过子查询进行非功能需求，在大部分情况下是可以支持的。比如分页、统计总数等；而通过子查询实现业务查询当前并不能支持。</p>

<p>由于归并的限制，子查询中包含聚合函数目前无法支持。</p>


      
      
      </div>
    </div>

    

    <div id="navigation">
        
        <a class="nav nav-prev" href="http://shardingjdbc.io/document/legacy/2.x/cn/02-guide/transaction/"> <i class="fa fa-chevron-left"></i></a>
        <a class="nav nav-next" href="http://shardingjdbc.io/document/legacy/2.x/cn/02-guide/test-framework/" style="margin-right: 0px;"><i class="fa fa-chevron-right"></i></a>
    </div>

    </section>
    <div style="left: -1000px; overflow: scroll; position: absolute; top: -1000px; border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;">
      <div style="border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;"></div>
    </div>
    <script src="http://ovfotjrsi.bkt.clouddn.com/docs/js/clipboard.min.js"></script>
    <script src="http://ovfotjrsi.bkt.clouddn.com/docs/js/perfect-scrollbar.min.js"></script>
    <script src="http://ovfotjrsi.bkt.clouddn.com/docs/js/perfect-scrollbar.jquery.min.js"></script>
    <script src="http://ovfotjrsi.bkt.clouddn.com/docs/js/jquery.sticky-kit.min.js"></script>
    <script src="http://ovfotjrsi.bkt.clouddn.com/docs/js/featherlight.min.js"></script>
    <script src="http://ovfotjrsi.bkt.clouddn.com/docs/js/html5shiv-printshiv.min.js"></script>
    <script src="http://ovfotjrsi.bkt.clouddn.com/docs/js/highlight.pack.js"></script>
    <script>hljs.initHighlightingOnLoad();</script>
    <script src="http://ovfotjrsi.bkt.clouddn.com/docs/js/learn.js"></script>
    <script src="http://ovfotjrsi.bkt.clouddn.com/docs/js/hugo-learn.js"></script>
    <script src="http://cdn.bootcss.com/highlight.js/9.8.0/highlight.min.js"></script>
<script>hljs.initHighlightingOnLoad();</script>

  </body>
</html>

